home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / libs / info / makedoc.c < prev    next >
C/C++ Source or Header  |  1995-11-13  |  12KB  |  487 lines

  1. /* makedoc.c -- Make DOC.C and FUNS.H from input files. */
  2. /* Changed for emx by Eberhard Mattes -- Nov 1995 */
  3.  
  4. /* This file is part of GNU Info, a program for reading online documentation
  5.    stored in Info format.
  6.  
  7.    Copyright (C) 1993 Free Software Foundation, Inc.
  8.  
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2, or (at your option)
  12.    any later version.
  13.  
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  
  23.    Written by Brian Fox (bfox@ai.mit.edu). */
  24.  
  25. /* This program grovels the contents of the source files passed as arguments
  26.    and writes out a file of function pointers and documentation strings, and
  27.    a header file which describes the contents.  This only does the functions
  28.    declared with DECLARE_INFO_COMMAND. */
  29.  
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <sys/types.h>
  33. #if defined (HAVE_SYS_FILE_H)
  34. #include <sys/file.h>
  35. #endif /* HAVE_SYS_FILE_H */
  36. #include <sys/stat.h>
  37. #include "general.h"
  38.  
  39. #if !defined (O_RDONLY)
  40. #if defined (HAVE_SYS_FCNTL_H)
  41. #include <sys/fcntl.h>
  42. #else /* !HAVE_SYS_FCNTL_H */
  43. #include <fcntl.h>
  44. #endif /* !HAVE_SYS_FCNTL_H */
  45. #endif /* !O_RDONLY */
  46.  
  47. extern void *xmalloc (), *xrealloc ();
  48. static void fatal_file_error ();
  49.  
  50. /* Name of the header file which receives the declarations of functions. */
  51. static char *funs_filename = "funs.h";
  52.  
  53. /* Name of the documentation to function pointer file. */
  54. static char *doc_filename = "doc.c";
  55.  
  56. static char *doc_header[] = {
  57.   "/* doc.c -- Generated structure containing function names and doc strings.",
  58.   "",
  59.   "   This file was automatically made from various source files with the",
  60.   "   command \"%s\".  DO NOT EDIT THIS FILE, only \"%s.c\".",
  61.   (char *)NULL
  62. };
  63.  
  64. static char *doc_header_1[] = {
  65.   "   An entry in the array FUNCTION_DOC_ARRAY is made for each command",
  66.   "   found in the above files; each entry consists of a function pointer,",
  67. #if defined (NAMED_FUNCTIONS)
  68.   "   a string which is the user-visible name of the function,",
  69. #endif /* NAMED_FUNCTIONS */
  70.   "   and a string which documents its purpose. */",
  71.   "",
  72.   "#include \"doc.h\"",
  73.   "#include \"funs.h\"",
  74.   "",
  75.   "FUNCTION_DOC function_doc_array[] = {",
  76.   "",
  77.   (char *)NULL
  78. };
  79.  
  80. /* How to remember the locations of the functions found so that Emacs
  81.    can use the information in a tag table. */
  82. typedef struct {
  83.   char *name;            /* Name of the tag. */
  84.   int line;            /* Line number at which it appears. */
  85.   long char_offset;        /* Character offset at which it appears. */
  86. } EMACS_TAG;
  87.  
  88. typedef struct {
  89.   char *filename;        /* Name of the file containing entries. */
  90.   long entrylen;        /* Total number of characters in tag block. */
  91.   EMACS_TAG **entries;        /* Entries found in FILENAME. */
  92.   int entries_index;
  93.   int entries_slots;
  94. } EMACS_TAG_BLOCK;
  95.  
  96. EMACS_TAG_BLOCK **emacs_tags = (EMACS_TAG_BLOCK **)NULL;
  97. int emacs_tags_index = 0;
  98. int emacs_tags_slots = 0;
  99.  
  100. #define DECLARATION_STRING "\nDECLARE_INFO_COMMAND"
  101.  
  102. static void process_one_file ();
  103. static void maybe_dump_tags ();
  104. static FILE *must_fopen ();
  105.  
  106. int
  107. main (argc, argv)
  108.      int argc;
  109.      char **argv;
  110. {
  111.   register int i;
  112.   int tags_only = 0;
  113.   FILE *funs_stream, *doc_stream;
  114.  
  115.   for (i = 1; i < argc; i++)
  116.     if (strcmp (argv[i], "-tags") == 0)
  117.       {
  118.     tags_only++;
  119.     break;
  120.       }
  121.  
  122.   if (tags_only)
  123.     {
  124.       funs_filename = "/dev/null";
  125.       doc_filename = "/dev/null";
  126.     }
  127.   
  128.   funs_stream = must_fopen (funs_filename, "w");
  129.   doc_stream = must_fopen (doc_filename, "w");
  130.  
  131.   fprintf (funs_stream,
  132.        "/* %s -- Generated declarations for Info commands. */\n",
  133.        funs_filename);
  134.  
  135.   for (i = 0; doc_header[i]; i++)
  136.     {
  137.       fprintf (doc_stream, doc_header[i], argv[0], argv[0]);
  138.       fprintf (doc_stream, "\n");
  139.     }
  140.  
  141.   fprintf (doc_stream,
  142.        "   Source files groveled to make this file include:\n\n");
  143.  
  144.   for (i = 1; i < argc; i++)
  145.     fprintf (doc_stream, "\t%s\n", argv[i]);
  146.  
  147.   fprintf (doc_stream, "\n");
  148.  
  149.   for (i = 0; doc_header_1[i]; i++)
  150.     fprintf (doc_stream, "%s\n", doc_header_1[i]);
  151.  
  152.  
  153.   for (i = 1; i < argc; i++)
  154.     {
  155.       char *curfile;
  156.       curfile = argv[i];
  157.  
  158.       if (*curfile == '-')
  159.     continue;
  160.  
  161.       fprintf (doc_stream, "/* Commands found in \"%s\". */\n", curfile);
  162.       fprintf (funs_stream, "\n/* Functions declared in \"%s\". */\n",
  163.            curfile);
  164.  
  165.       process_one_file (curfile, doc_stream, funs_stream);
  166.     }
  167.  
  168.   fprintf (doc_stream,
  169.        "   { (VFunction *)NULL, (char *)NULL, (char *)NULL }\n};\n");
  170.  
  171.   fclose (funs_stream);
  172.   fclose (doc_stream);
  173.  
  174.   if (tags_only)
  175.     maybe_dump_tags (stdout);
  176.   exit (0);
  177. }
  178.  
  179. /* Dumping out the contents of an Emacs tags table. */
  180. static void
  181. maybe_dump_tags (stream)
  182.      FILE *stream;
  183. {
  184.   register int i;
  185.  
  186.   /* Print out the information for each block. */
  187.   for (i = 0; i < emacs_tags_index; i++)
  188.     {
  189.       register int j;
  190.       register EMACS_TAG_BLOCK *block;
  191.       register EMACS_TAG *etag;
  192.       long block_len;
  193.  
  194.       block_len = 0;
  195.       block = emacs_tags[i];
  196.  
  197.       /* Calculate the length of the dumped block first. */
  198.       for (j = 0; j < block->entries_index; j++)
  199.     {
  200.       char digits[30];
  201.       etag = block->entries[j];
  202.       block_len += 3 + strlen (etag->name);
  203.       sprintf (digits, "%d,%d", etag->line, etag->char_offset);
  204.       block_len += strlen (digits);
  205.     }
  206.  
  207.       /* Print out the defining line. */
  208.       fprintf (stream, "\f\n%s,%d\n", block->filename, block_len);
  209.  
  210.       /* Print out the individual tags. */
  211.       for (j = 0; j < block->entries_index; j++)
  212.     {
  213.       etag = block->entries[j];
  214.  
  215.       fprintf (stream, "%s,\177%d,%d\n",
  216.            etag->name, etag->line, etag->char_offset);
  217.     }
  218.     }
  219. }
  220.  
  221. /* Keeping track of names, line numbers and character offsets of functions
  222.    found in source files. */
  223. static EMACS_TAG_BLOCK *
  224. make_emacs_tag_block (filename)
  225.      char *filename;
  226. {
  227.   EMACS_TAG_BLOCK *block;
  228.  
  229.   block = (EMACS_TAG_BLOCK *)xmalloc (sizeof (EMACS_TAG_BLOCK));
  230.   block->filename = strdup (filename);
  231.   block->entrylen = 0;
  232.   block->entries = (EMACS_TAG **)NULL;
  233.   block->entries_index = 0;
  234.   block->entries_slots = 0;
  235.   return (block);
  236. }
  237.  
  238. static void
  239. add_tag_to_block (block, name, line, char_offset)
  240.      EMACS_TAG_BLOCK *block;
  241.      char *name;
  242.      int line;
  243.      long char_offset;
  244. {
  245.   EMACS_TAG *tag;
  246.  
  247.   tag = (EMACS_TAG *)xmalloc (sizeof (EMACS_TAG));
  248.   tag->name = name;
  249.   tag->line = line;
  250.   tag->char_offset = char_offset;
  251.   add_pointer_to_array (tag, block->entries_index, block->entries,
  252.             block->entries_slots, 50, EMACS_TAG *);
  253. }
  254.  
  255. /* Read the file represented by FILENAME into core, and search it for Info
  256.    function declarations.  Output the declarations in various forms to the
  257.    DOC_STREAM and FUNS_STREAM. */
  258. static void
  259. process_one_file (filename, doc_stream, funs_stream)
  260.      char *filename;
  261.      FILE *doc_stream, *funs_stream;
  262. {
  263.   int descriptor, decl_len;
  264.   char *buffer, *decl_str;
  265.   struct stat finfo;
  266.   long offset;
  267.   long file_size;
  268.   EMACS_TAG_BLOCK *block;
  269.  
  270.   if (stat (filename, &finfo) == -1)
  271.     fatal_file_error (filename);
  272.  
  273.   descriptor = open (filename, O_RDONLY, 0666);
  274.  
  275.   if (descriptor == -1)
  276.     fatal_file_error (filename);
  277.  
  278.   file_size = (long) finfo.st_size;
  279.   buffer = (char *)xmalloc (1 + file_size);
  280. #ifdef EMX
  281.   file_size = read (descriptor, buffer, file_size);
  282. #else /* !EMX */
  283.   read (descriptor, buffer, file_size);
  284. #endif /* !EMX */
  285.   close (descriptor);
  286.  
  287.   offset = 0;
  288.   decl_str = DECLARATION_STRING;
  289.   decl_len = strlen (decl_str);
  290.  
  291.   block = make_emacs_tag_block (filename);
  292.  
  293.   while (1)
  294.     {
  295.       long point = 0;
  296.       long line_start = 0;
  297.       int line_number = 0;
  298.  
  299.       char *func, *doc;
  300. #if defined (NAMED_FUNCTIONS)
  301.       char *func_name;
  302. #endif /* NAMED_FUNCTIONS */
  303.  
  304.       for (; offset < (file_size - decl_len); offset++)
  305.     {
  306.       if (buffer[offset] == '\n')
  307.         {
  308.           line_number++;
  309.           line_start = offset + 1;
  310.         }
  311.  
  312.       if (strncmp (buffer + offset, decl_str, decl_len) == 0)
  313.         {
  314.           offset += decl_len;
  315.           point = offset;
  316.           break;
  317.         }
  318.     }
  319.  
  320.       if (!point)
  321.     break;
  322.  
  323.       /* Skip forward until we find the open paren. */
  324.       while (point < file_size)
  325.     {
  326.       if (buffer[point] == '\n')
  327.         {
  328.           line_number++;
  329.           line_start = point + 1;
  330.         }
  331.       else if (buffer[point] == '(')
  332.         break;
  333.  
  334.       point++;
  335.     }
  336.  
  337.       while (point++ < file_size)
  338.     {
  339.       if (!whitespace_or_newline (buffer[point]))
  340.         break;
  341.       else if (buffer[point] == '\n')
  342.         {
  343.           line_number++;
  344.           line_start = point + 1;
  345.         }
  346.     }
  347.  
  348.       if (point >= file_size)
  349.     break;
  350.  
  351.       /* Now looking at name of function.  Get it. */
  352.       for (offset = point; buffer[offset] != ','; offset++);
  353.       func = (char *)xmalloc (1 + (offset - point));
  354.       strncpy (func, buffer + point, offset - point);
  355.       func[offset - point] = '\0';
  356.  
  357.       /* Remember this tag in the current block. */
  358.       {
  359.     char *tag_name;
  360.  
  361.     tag_name = (char *)xmalloc (1 + (offset - line_start));
  362.     strncpy (tag_name, buffer + line_start, offset - line_start);
  363.     tag_name[offset - line_start] = '\0';
  364.     add_tag_to_block (block, tag_name, line_number, point);
  365.       }
  366.  
  367. #if defined (NAMED_FUNCTIONS)
  368.       /* Generate the user-visible function name from the function's name. */
  369.       {
  370.     register int i;
  371.     char *name_start;
  372.  
  373.     name_start = func;
  374.  
  375.     if (strncmp (name_start, "info_", 5) == 0)
  376.       name_start += 5;
  377.  
  378.     func_name = strdup (name_start);
  379.  
  380.     /* Fix up "ea" commands. */
  381.     if (strncmp (func_name, "ea_", 3) == 0)
  382.       {
  383.         char *temp_func_name;
  384.  
  385.         temp_func_name = (char *)xmalloc (10 + strlen (func_name));
  386.         strcpy (temp_func_name, "echo_area_");
  387.         strcat (temp_func_name, func_name + 3);
  388.         free (func_name);
  389.         func_name = temp_func_name;
  390.       }
  391.  
  392.     for (i = 0; func_name[i]; i++)
  393.       if (func_name[i] == '_')
  394.         func_name[i] = '-';
  395.       }
  396. #endif /* NAMED_FUNCTIONS */
  397.  
  398.       /* Find doc string. */
  399.       point = offset + 1;
  400.  
  401.       while (point < file_size)
  402.     {
  403.       if (buffer[point] == '\n')
  404.         {
  405.           line_number++;
  406.           line_start = point + 1;
  407.         }
  408.  
  409.       if (buffer[point] == '"')
  410.         break;
  411.       else
  412.         point++;
  413.     }
  414.  
  415.       offset = point + 1;
  416.  
  417.       while (offset < file_size)
  418.     {
  419.       if (buffer[offset] == '\n')
  420.         {
  421.           line_number++;
  422.           line_start = offset + 1;
  423.         }
  424.  
  425.       if (buffer[offset] == '\\')
  426.         offset += 2;
  427.       else if (buffer[offset] == '"')
  428.         break;
  429.       else
  430.         offset++;
  431.     }
  432.  
  433.       offset++;
  434.       if (offset >= file_size)
  435.     break;
  436.  
  437.       doc = (char *)xmalloc (1 + (offset - point));
  438.       strncpy (doc, buffer + point, offset - point);
  439.       doc[offset - point] = '\0';
  440.  
  441. #if defined (NAMED_FUNCTIONS)
  442.       fprintf (doc_stream, "   { %s, \"%s\", %s },\n", func, func_name, doc);
  443.       free (func_name);
  444. #else /* !NAMED_FUNCTIONS */
  445.       fprintf (doc_stream, "   { %s, %s },\n", func, doc);
  446. #endif /* !NAMED_FUNCTIONS */
  447.  
  448.       fprintf (funs_stream, "extern void %s ();\n", func);
  449.       free (func);
  450.       free (doc);
  451.     }
  452.   free (buffer);
  453.  
  454.   /* If we created any tags, remember this file on our global list.  Otherwise,
  455.      free the memory already allocated to it. */
  456.   if (block->entries)
  457.     add_pointer_to_array (block, emacs_tags_index, emacs_tags,
  458.               emacs_tags_slots, 10, EMACS_TAG_BLOCK *);
  459.   else
  460.     {
  461.       free (block->filename);
  462.       free (block);
  463.     }
  464. }
  465.  
  466. static void
  467. fatal_file_error (filename)
  468.      char *filename;
  469. {
  470.   fprintf (stderr, "Couldn't manipulate the file %s.\n", filename);
  471.   exit (2);
  472. }
  473.  
  474. static FILE *
  475. must_fopen (filename, mode)
  476.      char *filename, *mode;
  477. {
  478.   FILE *stream;
  479.  
  480.   stream = fopen (filename, mode);
  481.   if (!stream)
  482.     fatal_file_error (filename);
  483.  
  484.   return (stream);
  485. }
  486.  
  487.